home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / pluginy Firefox / 3006 / 3006.xpi / components / dhTwitterProcessor.js < prev    next >
Text File  |  2010-01-15  |  15KB  |  421 lines

  1. /******************************************************************************
  2.  *            Copyright (c) 2009 Michel Gutierrez. All Rights Reserved.
  3.  ******************************************************************************/
  4.  
  5. /**
  6.  * Constants.
  7.  */
  8.  
  9. const NS_TWITTER_CID = Components.ID("{e7933021-dbbb-493f-8b68-e0b74c2c1fea}");
  10. const NS_TWITTER_PROG_ID = "@downloadhelper.net/twitter-processor;1";
  11. const DHNS = "http://downloadhelper.net/1.0#";
  12.  
  13. var Util=null;
  14. var IOS=null;
  15.  
  16. /**
  17. * Object constructor
  18. */
  19. function Twitter() {
  20.     try {
  21.         //dump("[Twitter] constructor\n");
  22.         if(!Util.priorTo19()) {
  23.             var prefService=Components.classes["@mozilla.org/preferences-service;1"]
  24.                                                .getService(Components.interfaces.nsIPrefService);
  25.             this.pref=prefService.getBranch("dwhelper.twitter.");
  26.             this.core=Components.classes["@downloadhelper.net/core;1"].
  27.                 getService(Components.interfaces.dhICore);
  28.             this.core.registerProcessor(this);
  29.         }
  30.     } catch(e) {
  31.         dump("[Twitter] !!! constructor: "+e+"\n");
  32.     }
  33. }
  34.  
  35. Twitter.prototype = {
  36.         get username() { return this.pref.getCharPref("username"); },
  37.         get password() { var pw=Util.getPassword("twitter"); if(pw==null) pw=""; return pw; },
  38.         get name() { return "twitter-update"; },
  39.         get provider() { return "DownloadHelper"; },
  40.         get title() { return Util.getText("twitter.update.title"); },
  41.         get description() { return Util.getText("twitter.update.description"); },
  42.         get enabled() { return this.pref.getBoolPref("enabled"); },
  43. }
  44.  
  45. Twitter.prototype.canHandle=function(desc) {
  46.     //dump("[Twitter] canHandle()\n");
  47.     var extension=Util.getPropsString(desc,"file-extension");
  48.     if(extension=="flv" || extension=="mp4")
  49.         return true;
  50.     else
  51.         return false;
  52. }
  53.  
  54. Twitter.prototype.requireDownload=function(desc) {
  55.     //dump("[Twitter] requireDownload()\n");
  56.     return false;
  57. }
  58.     
  59. Twitter.prototype.preDownload=function(desc) {
  60.     //dump("[Twitter] preDownload()\n");
  61.     return false;
  62. }
  63.  
  64. Twitter.prototype.handle=function(desc) {
  65.     //dump("[Twitter] handle()\n");
  66.     if(this.username.length==0) {
  67.         Util.alertWarning(Util.getText("twitter.message.configure-account"));
  68.         this.openPreferences();
  69.         return;
  70.     }
  71.     function VerifyCredentialsObserver(client) {
  72.         this.client=client;
  73.     }
  74.     VerifyCredentialsObserver.prototype={
  75.         observe: function(subject,topic,data) {
  76.             if(topic=="twitter-credentials") {
  77.                 if(data=="succeeded") {
  78.                     try {
  79.                         var purl=Util.getPropsString(desc,"page-url");
  80.                         var murl=Util.getPropsString(desc,"media-url");
  81.                         var extension=Util.getPropsString(desc,"file-extension");
  82.                         var title=Util.getPropsString(desc,"file-name");
  83.                         var smartnaming=false;
  84.                         if(desc.has("sn-name")) {
  85.                             smartnaming=true;
  86.                             title=Util.getPropsString(desc,"sn-name");
  87.                         }
  88.                         var description="";
  89.                         if(desc.has("sn-descr")) {
  90.                             smartnaming=true;
  91.                             description=Util.getPropsString(desc,"sn-descr");
  92.                         }
  93.                         var xml=[
  94.                                  "<?xml version='1.0' encoding='utf-8'?>\n<media>\n",
  95.                                  "  <purl>",Util.xmlEscape(purl),"</purl>\n",
  96.                                  "  <murl>",Util.xmlEscape(murl),"</murl>\n",
  97.                                  "  <title>",Util.xmlEscape(title),"</title>\n",
  98.                                  "  <description>",Util.xmlEscape(description),"</description>\n",
  99.                                  "  <extension>",Util.xmlEscape(extension),"</extension>\n",
  100.                                  "  <smartname>",""+smartnaming,"</smartname>\n",
  101.                                  "</media>"
  102.                                  ].join("");
  103.                         var url="http://vdh.bz/set-xml.php";
  104.                         var uri = IOS.newURI(url, null, null);
  105.                         var channel = IOS.newChannelFromURI(uri);
  106.                         var httpChannel = channel.QueryInterface(Components.interfaces.nsIHttpChannel);
  107.                         var listener = new XMLStreamListener(this.client,"gotLink",{entry: desc, purl: purl, murl: murl, title: title, description: description, 
  108.                             smartnaming: smartnaming });
  109.                         channel.notificationCallbacks = listener;
  110.  
  111.                         var pipe=Components.classes["@mozilla.org/pipe;1"].
  112.                             createInstance(Components.interfaces.nsIPipe);
  113.                         pipe.init(true,false,1024,10,null);
  114.                         var charset = "UTF-8"; // Can be any character encoding name that Mozilla supports
  115.  
  116.                         var os = Components.classes["@mozilla.org/intl/converter-output-stream;1"]
  117.                                            .createInstance(Components.interfaces.nsIConverterOutputStream);
  118.                         os.init(pipe.outputStream, charset, 0, 0x0000);
  119.                         os.writeString(xml);
  120.                         os.close();
  121.  
  122.                         var uploadChannel = channel.QueryInterface(Components.interfaces.nsIUploadChannel);
  123.                         uploadChannel.setUploadStream(pipe.inputStream, "application/x-binary", -1);
  124.  
  125.                         httpChannel.requestMethod = "POST";    
  126.                         channel.asyncOpen(listener, null);
  127.                     } catch(e) {
  128.                         dump("!!! [Twitter] handle()/getLink: "+e+"\n");
  129.                     }
  130.                 } else {
  131.                     Util.alertError(Util.getText("twitter.message.account-failed"));
  132.                     this.client.openPreferences();
  133.                 }
  134.             }
  135.         }
  136.     }
  137.     this.verifyCredentials(new VerifyCredentialsObserver(this));
  138. }
  139.  
  140. Twitter.prototype.gotLink=function(args,status,doc,httpStatus,text) {
  141.     //dump("[Twitter] gotLink("+args+","+status+","+doc+","+httpStatus+",<text>)\n<text>="+text+")\n");
  142.     try {
  143.         if(httpStatus!=200 || doc==null || Util.xpGetString(doc.documentElement,"/result/status")!="success") {
  144.             Util.alertError(Util.getText("twitter.message.cannot-get-short-url"));
  145.         } else {
  146.             var url=Util.xpGetString(doc.documentElement,"/result/url");
  147.             var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
  148.                                         .getService(Components.interfaces.nsIWindowMediator);
  149.             var window = wm.getMostRecentWindow("navigator:browser");
  150.             var options="chrome,centerscreen,toolbar,modal";
  151.             
  152.             var message=url;
  153.             if(this.pref.getBoolPref("tag-message"))
  154.                 message+=" #vidohe";
  155.             
  156.             if(this.twitterLength(args.title+".. "+message)>140) {
  157.                 var title=args.title;
  158.                 var txt=title+".. "+message;
  159.                 while(this.twitterLength(txt)>140) {
  160.                     title=title.substr(0,title.length-1);
  161.                     txt=title+".. "+message;
  162.                 }
  163.                 message=txt;
  164.             } else {
  165.                 if(this.twitterLength(args.title+" "+args.description+" "+message)>140) {
  166.                     var description=args.description;
  167.                     var txt=args.title+" - "+description+".. "+message;
  168.                     while(this.twitterLength(txt)>140) {
  169.                         description=description.substr(0,description.length-1);
  170.                         txt=args.title+" - "+description+".. "+message;
  171.                     }
  172.                     message=txt;
  173.                 } else {
  174.                     message=args.title+" - "+args.description+" "+message;
  175.                 }
  176.             }
  177.             
  178.             var data={ url: url, message: message, user: this.username, smartnaming: args.smartnaming };
  179.             window.openDialog("chrome://dwhelper/content/twitter-message.xul",'',options, data );
  180.         }
  181.     } catch(e) {
  182.         dump("[Twitter] gotLink(): "+e+"\n");
  183.     }
  184. }
  185.  
  186. Twitter.prototype.twitterLength=function(text) {
  187.  
  188.     var txt=text.replace(/&/g,"&");
  189.     var txt=txt.replace(/</g,"<");
  190.     var txt=txt.replace(/>/g,">");
  191.  
  192.     var string = txt.replace(/\r\n/g,"\n");
  193.     var utftext = "";
  194.     for (var n = 0; n < string.length; n++) {
  195.         var c = string.charCodeAt(n);
  196.         if (c < 128) {
  197.             utftext += String.fromCharCode(c);
  198.         }
  199.         else if((c > 127) && (c < 2048)) {
  200.             utftext += String.fromCharCode((c >> 6) | 192);
  201.             utftext += String.fromCharCode((c & 63) | 128);
  202.         }
  203.         else {
  204.             utftext += String.fromCharCode((c >> 12) | 224);
  205.             utftext += String.fromCharCode(((c >> 6) & 63) | 128);
  206.             utftext += String.fromCharCode((c & 63) | 128);
  207.         }
  208.     }
  209.     return utftext.length;
  210. }
  211.  
  212. Twitter.prototype.openPreferences=function() {
  213.     var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
  214.                                 .getService(Components.interfaces.nsIWindowMediator);
  215.     var window = wm.getMostRecentWindow("navigator:browser");
  216.     var options="chrome,centerscreen,toolbar,modal";
  217.     var data={ selectedPanel: "panel-services", selectedTab: "tab-twitter" }
  218.     window.openDialog("chrome://dwhelper/content/preferences-new.xul",'',options, data );    
  219. }
  220.  
  221.  
  222.  
  223. Twitter.prototype.updateHandler=function(args,status,doc,httpStatus,text) {
  224.     //dump("[Twitter] updateHandler("+args+","+status+","+doc+","+httpStatus+",<text>)\n<text>="+text+")\n");
  225. }
  226.  
  227. Twitter.prototype.callAPI=function(path,method,callback,args) {
  228.     //dump("[Twitter] callAPI("+path+","+method+",callback,args)\n");
  229.     try {
  230.         var url="http://twitter.com/"+path;
  231.         var uri = IOS.newURI(url, null, null);
  232.         var channel = IOS.newChannelFromURI(uri);
  233.         var httpChannel = channel.QueryInterface(Components.interfaces.nsIHttpChannel);
  234.         httpChannel.setRequestHeader("Authorization","Basic "+Util.base64Encode(this.username+":"+this.password),false);
  235.         httpChannel.requestMethod = method;    
  236.         var listener = new XMLStreamListener(this,callback,args);
  237.         channel.notificationCallbacks = listener;
  238.         channel.asyncOpen(listener, null);
  239.     } catch(e) {
  240.         dump("!!! [Twitter] callAPI(): "+e+"\n");
  241.     }
  242. }
  243.  
  244. Twitter.prototype.update=function(message) {
  245.     //dump("[Twitter] update("+message+")\n");
  246.     this.callAPI("statuses/update.xml?status=" +encodeURIComponent(message),"POST","updateHandler",null);
  247. }
  248.  
  249. Twitter.prototype.verifyCredentialsHandler=function(args,status,doc,httpStatus,text) {
  250.     //dump("[Twitter] verifyCredentialsHandler("+args+","+status+","+doc+","+httpStatus+",<text>)\n<text>="+text+")\n");
  251.     var status;
  252.     if(httpStatus==200)
  253.         status="succeeded";
  254.     else
  255.         status="failed";
  256.     this.pref.setCharPref("last-status",status);
  257.     args.observer.observe(this,"twitter-credentials",status);
  258. }
  259.  
  260. Twitter.prototype.verifyCredentials=function(observer) {
  261.     //dump("[Twitter] verifyCredentials()\n");
  262.     this.callAPI("account/verify_credentials.xml","GET","verifyCredentialsHandler",{observer:observer});
  263. }
  264.  
  265. Twitter.prototype.QueryInterface = function(iid) {
  266.     //dump("[Twitter] QueryInterface("+iid+")\n");
  267.     if(
  268.            iid.equals(Components.interfaces.dhITwitter) ||
  269.            iid.equals(Components.interfaces.dhIProcessor) ||
  270.         iid.equals(Components.interfaces.nsISupports)
  271.     ) {
  272.         return this;
  273.     }
  274.     throw Components.results.NS_ERROR_NO_INTERFACE;
  275. }
  276.  
  277. var vTwitterModule = {
  278.     firstTime: true,
  279.     
  280.     /*
  281.      * RegisterSelf is called at registration time (component installation
  282.      * or the only-until-release startup autoregistration) and is responsible
  283.      * for notifying the component manager of all components implemented in
  284.      * this module.  The fileSpec, location and type parameters are mostly
  285.      * opaque, and should be passed on to the registerComponent call
  286.      * unmolested.
  287.      */
  288.     registerSelf: function (compMgr, fileSpec, location, type) {
  289.  
  290.         if (this.firstTime) {
  291.             this.firstTime = false;
  292.             throw Components.results.NS_ERROR_FACTORY_REGISTER_AGAIN;
  293.         }
  294.         compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
  295.         compMgr.registerFactoryLocation(NS_TWITTER_CID,
  296.                                         "Twitter",
  297.                                         NS_TWITTER_PROG_ID, 
  298.                                         fileSpec,
  299.                                         location,
  300.                                         type);
  301.     },
  302.  
  303.     unregisterSelf: function(compMgr, fileSpec, location) {
  304.         compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
  305.         compMgr.unregisterFactoryLocation(NS_DH_TWITTER_CID, fileSpec);
  306.     },
  307.  
  308.     /*
  309.      * The GetClassObject method is responsible for producing Factory and
  310.      * SingletonFactory objects (the latter are specialized for services).
  311.      */
  312.     getClassObject: function (compMgr, cid, iid) {
  313.         if (!cid.equals(NS_TWITTER_CID)) {
  314.             throw Components.results.NS_ERROR_NO_INTERFACE;
  315.         }
  316.  
  317.         if (!iid.equals(Components.interfaces.nsIFactory)) {
  318.             throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
  319.         }
  320.  
  321.         return this.vTwitterFactory;
  322.     },
  323.  
  324.     /* factory object */
  325.     vTwitterFactory: {
  326.         /*
  327.          * Construct an instance of the interface specified by iid, possibly
  328.          * aggregating it with the provided outer.  (If you don't know what
  329.          * aggregation is all about, you don't need to.  It reduces even the
  330.          * mightiest of XPCOM warriors to snivelling cowards.)
  331.          */
  332.         createInstance: function (outer, iid) {
  333.             if (outer != null) {
  334.                 throw Components.results.NS_ERROR_NO_AGGREGATION;
  335.             }
  336.     
  337.             if(Util==null) 
  338.                 Util=Components.classes["@downloadhelper.net/util-service;1"]
  339.                     .getService(Components.interfaces.dhIUtilService);
  340.             if(IOS==null)
  341.                 IOS= Components.classes["@mozilla.org/network/io-service;1"]
  342.                     .getService(Components.interfaces.nsIIOService);
  343.  
  344.             return new Twitter().QueryInterface(iid);
  345.         }
  346.     },
  347.  
  348.     /*
  349.      * The canUnload method signals that the component is about to be unloaded.
  350.      * C++ components can return false to indicate that they don't wish to be
  351.      * unloaded, but the return value from JS components' canUnload is ignored:
  352.      * mark-and-sweep will keep everything around until it's no longer in use,
  353.      * making unconditional ``unload'' safe.
  354.      *
  355.      * You still need to provide a (likely useless) canUnload method, though:
  356.      * it's part of the nsIModule interface contract, and the JS loader _will_
  357.      * call it.
  358.      */
  359.     canUnload: function(compMgr) {
  360.         return true;
  361.     }
  362. };
  363.  
  364. function NSGetModule(compMgr, fileSpec) {
  365.     return vTwitterModule;
  366. }
  367.  
  368. function XMLStreamListener(service,callback,args) {
  369.     this.service=service;
  370.     this.callback=callback;
  371.     this.args=args;
  372. }
  373.  
  374. XMLStreamListener.prototype={
  375.     QueryInterface: function(iid) {
  376.         if (iid.equals(Components.interfaces.nsISupports) || 
  377.             iid.equals(Components.interfaces.nsIInterfaceRequestor) ||
  378.             iid.equals(Components.interfaces.nsIStreamListener)) {
  379.             return this;
  380.         }
  381.         throw Components.results.NS_ERROR_NO_INTERFACE;
  382.     },
  383.     onStartRequest: function(request,context) {
  384.         this.data="";
  385.     },
  386.     onDataAvailable: function(request,context,inputStream,offset,count) {
  387.         var sstream = Components.classes["@mozilla.org/intl/converter-input-stream;1"]
  388.                .createInstance(Components.interfaces.nsIConverterInputStream);
  389.         sstream.init(inputStream, "utf-8", 256, 
  390.             Components.interfaces.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);
  391.  
  392.         var str={};
  393.         var n=sstream.readString(128,str);
  394.         while(n>0) {
  395.             this.data+=str.value;
  396.             str={};
  397.             n=sstream.readString(128,str);
  398.         }
  399.     },
  400.     onStopRequest: function(request,context,nsresult) {
  401.         var responseStatus=request.QueryInterface(Components.interfaces.nsIHttpChannel).responseStatus;
  402.         if(responseStatus==200) {
  403.             var parser=Components.classes["@mozilla.org/xmlextras/domparser;1"].
  404.                 createInstance(Components.interfaces.nsIDOMParser);
  405.             var doc=parser.parseFromString(this.data,"text/xml");
  406.             this.service[this.callback](this.args,true,doc,responseStatus,this.data);
  407.         } else {
  408.             this.service[this.callback](this.args,false,null,responseStatus,this.data);
  409.         }
  410.     },
  411.     getInterface: function(iid) {
  412.         if (iid.equals(Components.interfaces.nsISupports) || 
  413.             iid.equals(Components.interfaces.nsIInterfaceRequestor) ||
  414.             iid.equals(Components.interfaces.nsIStreamListener)) {
  415.             return this;
  416.         }
  417.         return null;
  418.     },
  419. }
  420.  
  421.